package com.dao;

import com.entity.Qm;
import com.util.DBpool.DBconnection;
import com.util.FileUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.util.GlobalArgs.*;
import static com.util.StrUtil.*;

/**
 * Created by wlc on 2018/1/2.
 */
public class QmDao {
    /**
     * 将QM数据存储到数据库中
     * @param qm
     */
    public static void data_save(Qm qm,String calculateObject){
        DBconnection saveInDB = new DBconnection();
        //part1
        saveInDB.setSheet_name("QM_USER_AND_PBC");
        saveInDB.saveDataToDB(qm.getQM_USER_AND_PBC());
        //part2
        switch (calculateObject){
            case "溶质溶剂":saveInDB.setSheet_name("QM_CalculationObject_SolventSolute");break;
            case "晶体":saveInDB.setSheet_name("QM_CalculationObject_Crystal");break;
            case "Cluster":saveInDB.setSheet_name("QM_CalculationObject_Crystal");break;
            case "Slab模型":saveInDB.setSheet_name("QM_CalculationObject_Slab");break;
        }
        saveInDB.saveDataToDB(qm.getQM_Calculation_object());
        //part3
        saveInDB.setSheet_name("QM_Electronic_Structure_Quantum_Mechanics_Calculation");
        saveInDB.saveDataToDB(qm.getQM_Electronic_Structure_Quantum_Mechanics_Calculation());
        //part4
        saveInDB.setSheet_name("QM_Ground_state");
        saveInDB.saveDataToDB(qm.getQM_Ground_state_excited_state());
    }

    /**
     * 从磁盘中读取分析log文件
     * @param log_file_path
     * @param log_file_name
     * @return
     * @throws IOException
     */
    public static HashMap<String,String> readAndProcess_logFile(String log_file_path,String log_file_name) throws IOException{
        ArrayList<String> log_file_content = FileUtil.readFile(log_file_path);
        HashMap<String,String> form_data = new HashMap<String,String>(){{
            put("ErrorTermination", "False");
            put("Stoichiometry","null");
            put("Solute_Charge", "null");
            put("Solute_Multiplicity","null");
            put("Solute_CAS","null");
            put("Program","null");
            put("Sub_system_program","null");
            put("node","null");
            put("Calculate_base_set","null");
            put("Gaussian_Keywords", "null");
            put("energy","null");
            put("Basis_function","null");
            put("atomic","null");
            put("x_coor","null");
            put("y_coor","null");
            put("z_coor","null");
            put("Mulliken","null");
            put("LUMO", "null");
            put("LUMO+1", "null");
            put("HOMO", "null");
            put("HOMO-1", "null");
            put("HOMO_LUMO","null");
            put("X", "null");
            put("Y", "null");
            put("Z", "null");
            put("Tot","null");
            put("XX","null");
            put("YY", "null");
            put("ZZ","null");
            put("XY", "null");
            put("XZ", "null");
            put("YZ","null");
            put("XXX", "null");
            put("YYY", "null");
            put("ZZZ", "null");
            put("XYY", "null");
            put("XXY", "null");
            put("XXZ", "null");
            put("XZZ", "null");
            put("YZZ", "null");
            put("YYZ", "null");
            put("XYZ", "null");
            put("Frequencies","null");
            put("Zero_calibration","null");
            put("Free_Energy","null");
            put("entropy", "null");
            put("Accessible_surface","null");
        }};
        boolean[] decision = {true,true,true,true,true};
        String fres = "";
        for (int i = 0;i<log_file_content.size();i++){
            if (log_file_content.get(i).contains("Error termination")){
                form_data.replace("ErrorTermination","True");
                break;
            }
            if (log_file_content.get(i).contains("*")&&decision[0]){
                form_data.replace("Program",log_file_content.get(i+1).split(":")[0]);
                form_data.replace("Sub_system_program", getNullEmptyString(log_file_content.get(i+1).split(":")[1].split(" "),0));
                decision[0] = false;
            }
            if (log_file_content.get(i).contains("nprocs")&&decision[1]){
                form_data.replace("node",log_file_content.get(i).split("=")[1]);
                decision[1] = false;
            }
            if (log_file_content.get(i).contains("--------------")&&decision[2]&&!decision[1]){
                ArrayList<String> temp_gauss = getNullEmptyStringArray(log_file_content.get(i+1).split(" "));
                if (temp_gauss.size()>=4){
                    form_data.replace("Calculate_base_set",temp_gauss.get(temp_gauss.size()-2));
                    temp_gauss.remove(0);
                    temp_gauss.remove(temp_gauss.size()-1);
                    temp_gauss.remove(temp_gauss.size()-1);
                    form_data.replace("Gaussian_Keywords", StringUtils.join(temp_gauss," "));
                }else {
                    form_data.replace("Calculate_base_set",temp_gauss.get(1));
                }
                decision[2] = false;
            }
            if (log_file_content.get(i).contains("Charge")&&decision[3]){
                form_data.replace("Solute_Charge", getNullEmptyString(log_file_content.get(i).split("=")[1].split(" "),0));
                form_data.replace("Solute_Multiplicity",log_file_content.get(i).split("=")[2]);
                String[] cas_arr = log_file_name.split("\\.")[0].split("_");
                if (cas_arr.length == 4){
                    form_data.replace("Solute_CAS",cas_arr[1]+"_"+cas_arr[2]+"_"+cas_arr[3]);
                }
                decision[3] = false;
            }
            if (log_file_content.get(i).contains("Stoichiometry")&&decision[4]){
                String element = splitElementAndNum(getNullEmptyString(log_file_content.get(i).split(" "),1));
                form_data.replace("Stoichiometry",element);
                decision[4] = false;
            }
            if (log_file_content.get(i).contains("Coordinates (Angstroms)")){
                String atomic = "";
                String x_coor = "";
                String y_coor = "";
                String z_coor = "";
                for(int j = 3; !log_file_content.get(i+j).contains("--------------");j++){
                    ArrayList<String> temp_coor = getNullEmptyStringArray(log_file_content.get(i+j).split(" "));
                    atomic = atomic + temp_coor.get(1) + ";";
                    x_coor = x_coor + temp_coor.get(3) + ";";
                    y_coor = y_coor + temp_coor.get(4) + ";";
                    z_coor = z_coor + temp_coor.get(5) + ";";
                }
                form_data.replace("atomic",atomic);
                form_data.replace("x_coor",x_coor);
                form_data.replace("y_coor",y_coor);
                form_data.replace("z_coor",z_coor);
            }
            if (log_file_content.get(i).contains("Alpha  occ")&&log_file_content.get(i+1).contains("Alpha virt")){
                ArrayList<String> Alpha_occ = getNullEmptyStringArray(log_file_content.get(i).split("--")[1].split(" "));
                if (Alpha_occ.size() == 1){
                    form_data.replace("HOMO", Alpha_occ.get(0));
                    if (log_file_content.get(i-1).split("--").length>1){
                        form_data.replace("HOMO-1", getNullEmptyString(log_file_content.get(i-1).split("--")[1].split(" "),-1));
                    }
                }else {
                    form_data.replace("HOMO-1", getNullEmptyString(log_file_content.get(i).split("--")[1].split(" "),-2));
                    form_data.replace("HOMO", getNullEmptyString(log_file_content.get(i).split("--")[1].split(" "),-1));
                }
                form_data.replace("LUMO", getNullEmptyString(log_file_content.get(i+1).split("--")[1].split(" "),0));
                form_data.replace("LUMO+1", getNullEmptyString(log_file_content.get(i+1).split("--")[1].split(" "),1));
                Double HOMO_LUMO= Double.parseDouble(form_data.get("HOMO"))-Double.parseDouble(form_data.get("LUMO"));
                HOMO_LUMO = (double)Math.round(HOMO_LUMO*100000)/100000;
                form_data.replace("HOMO_LUMO",HOMO_LUMO.toString());
            }
            if (log_file_content.get(i).contains("Dipole moment")){
                form_data.replace("X", getNullEmptyString(log_file_content.get(i+1).split(" "),1));
                form_data.replace("Y", getNullEmptyString(log_file_content.get(i+1).split(" "),3));
                form_data.replace("Z", getNullEmptyString(log_file_content.get(i+1).split(" "),5));
                form_data.replace("Tot", getNullEmptyString(log_file_content.get(i+1).split(" "),7));
            }
            if (log_file_content.get(i).contains("Quadrupole moment")){
                form_data.replace("XX", getNullEmptyString(log_file_content.get(i+1).split(" "),1));
                form_data.replace("YY", getNullEmptyString(log_file_content.get(i+1).split(" "),3));
                form_data.replace("ZZ", getNullEmptyString(log_file_content.get(i+1).split(" "),5));
                form_data.replace("XY", getNullEmptyString(log_file_content.get(i+2).split(" "),1));
                form_data.replace("XZ", getNullEmptyString(log_file_content.get(i+2).split(" "),3));
                form_data.replace("YZ", getNullEmptyString(log_file_content.get(i+2).split(" "),5));
            }
            if (log_file_content.get(i).contains("Octapole moment")){
                ArrayList<String> Octapole_moment1 = getNullEmptyStringArray(log_file_content.get(i+1).split(" "));
                ArrayList<String> Octapole_moment2 = getNullEmptyStringArray(log_file_content.get(i+2).split(" "));
                ArrayList<String> Octapole_moment3 = getNullEmptyStringArray(log_file_content.get(i+3).split(" "));
                form_data.replace("XXX", Octapole_moment1.get(1));
                form_data.replace("YYY", Octapole_moment1.get(3));
                form_data.replace("ZZZ", Octapole_moment1.get(5));
                form_data.replace("XYY", Octapole_moment1.get(7));
                form_data.replace("XXY", Octapole_moment2.get(1));
                form_data.replace("XXZ", Octapole_moment2.get(3));
                form_data.replace("XZZ", Octapole_moment2.get(5));
                form_data.replace("YZZ", Octapole_moment2.get(7));
                form_data.replace("YYZ", Octapole_moment3.get(1));
                form_data.replace("XYZ", Octapole_moment3.get(3));
            }
            if (log_file_content.get(i).contains("Frequencies")){
                ArrayList<String> temp_fre = getNullEmptyStringArray(log_file_content.get(i).split(" "));
                temp_fre.remove(0);
                temp_fre.remove(0);
                fres = fres + StringUtils.join(temp_fre.toArray(),";") + ";";
            }
            if (log_file_content.get(i).contains("Mulliken")&&log_file_content.get(i).contains("charges:")){
                String Mulliken = "";
                for(int j = 2; !log_file_content.get(i+j).contains("Sum of Mulliken");j++){
                    ArrayList<String> temp_Mulliken = getNullEmptyStringArray(log_file_content.get(i+j).split(" "));
                    Mulliken = Mulliken + temp_Mulliken.get(2) + ";";
                }
                form_data.replace("Mulliken",Mulliken);
            }
            if (log_file_content.get(i).contains("Zero-point correction")){
                form_data.replace("Zero_calibration",getNullEmptyString(log_file_content.get(i).split(" "),2));
            }
            if (log_file_content.get(i).contains("Sum of electronic and thermal Free Energies")){
                form_data.replace("Free_Energy",getNullEmptyString(log_file_content.get(i).split("=")[1].split(" "),0));
                form_data.replace("entropy", getNullEmptyString(log_file_content.get(i+4).split(" "),3));
                break;
            }
            if (log_file_content.get(i).contains("SCF Done:")){
                form_data.replace("energy",getNullEmptyString(log_file_content.get(i).split(" "),4));
            }
            if (log_file_content.get(i).contains("primitive gaussians")&&log_file_content.get(i).contains("cartesian basis functions")){
                form_data.replace("Basis_function",getNullEmptyString(log_file_content.get(i).split(" "),0));
            }
        }
        if (!fres.equals("")){
            form_data.replace("Frequencies",fres);
        }

        return form_data;
    }

    /**
     * 从磁盘中读取分析dat文件
     * @param dat_file_path
     * @param log_file_name
     * @return
     * @throws IOException
     */
    public static String readAndProcess_datFile(String dat_file_path,String log_file_name) throws IOException{
        ArrayList<String> dat_file_content = FileUtil.readFile(dat_file_path);
        for (int i = 0;i<dat_file_content.size();i++){
            if (dat_file_content.get(i).contains(log_file_name.split("_")[1])){
                return getNullEmptyString(dat_file_content.get(i).split(" "),1);
            }
        }
        return "null";
    }

    /**
     * 从磁盘中读取分析GEBF所需文件
     * @param keys_file_path
     * @param cha_file_path
     * @param txt_file_path
     * @return
     * @throws Exception
     */
    public static HashMap<String,String> readAndProcess_GEBFFile(String keys_file_path,
                                                                 String cha_file_path,
                                                                 String txt_file_path,
                                                                 String log_file_path) throws Exception{
        ArrayList<String> content = new ArrayList<>();
        HashMap<String,String> form_data = new HashMap<String,String>(){{
            put("Subsystem_calculates_memory","null");
            put("Subsystem_parallel_number","null");
            put("Calculate_base_set","null");
            put("The_maximum_number_of_sub_system_blocks","null");
            put("Block_method2","null");
            put("Cut_off_the_distance","null");
            put("Charge","null");
            put("BSSE_correction","null");
            put("Double_center","null");
            put("Two_body","null");
            put("Three_body","null");
            put("atomic","null");
            put("The_total_number_of_sub_system","null");
            put("The_maximum_number_of_basis_functions","null");
            put("HF_energy","null");
            put("MP2_energy","null");
            put("CCSD_energy","null");
            put("Program", "null");
            put("Sub_system_program", "null");

        }};
        //读取keys文件内容
        content = FileUtil.readFile(keys_file_path);
        for (int i = 0;i<content.size();i++){
            if (content.get(i).contains("main_mem")){
                form_data.put("Subsystem_calculates_memory",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("main_nproc")){
                form_data.put("Subsystem_parallel_number",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("main_basis")){
                form_data.put("Calculate_base_set",content.get(i).split("=")[1].replaceAll("'",""));
            }
            if (content.get(i).contains("lsqc_maxsubfrag")){
                form_data.put("The_maximum_number_of_sub_system_blocks",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("lsqc_frag")){
                form_data.put("Block_method2",content.get(i).split("=")[1].replaceAll("'",""));
            }
            if (content.get(i).contains("lsqc_dis")){
                form_data.put("Cut_off_the_distance",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("lsqc_charge")){
                form_data.put("Charge",content.get(i).split("=")[1].replaceAll("'","").toLowerCase());
            }
            if (content.get(i).contains("lsqc_bsse")){
                form_data.put("BSSE_correction",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("lsqc_twofc")){
                form_data.put("Double_center",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("lsqc_twofrag")){
                form_data.put("Two_body",content.get(i).split("=")[1]);
            }
            if (content.get(i).contains("lsqc_trifrag")){
                form_data.put("Three_body",content.get(i).split("=")[1]);
            }
        }
        content.clear();
        //读取cha文件内容
        content = FileUtil.readFile(cha_file_path);
        String charge = "";
        String atomic = "";
        for (int i = 0;i<content.size();i++){
            ArrayList<String> temp_content = getNullEmptyStringArray(content.get(i).split(" "));
            atomic = atomic + temp_content.get(1) + ";";
            charge = charge + temp_content.get(2) + ";";
        }
        if (!charge.equals("")){
            form_data.put("atomic",atomic);
            form_data.put(form_data.get("Charge"),charge);
        }
        content.clear();
        //读取txt文件内容
        content = FileUtil.readFile(txt_file_path);
        String CCSD_energy = "";
        for (int i = 0;i<content.size();i++){
            if (content.get(i).contains("maxi")){
                form_data.put("The_total_number_of_sub_system",getNullEmptyString(content.get(i-1).split(" "),0));
                form_data.put("The_maximum_number_of_basis_functions",getNullEmptyString(content.get(i).split(" "),2));
            }
            if (content.get(i).contains("SCF")){
                form_data.put("HF_energy",getNullEmptyString(content.get(i).split(" "),2));
            }
            if (content.get(i).contains("MP2")){
                form_data.put("MP2_energy",getNullEmptyString(content.get(i).split(" "),2));
            }
            if (content.get(i).contains("CCSD")){
                CCSD_energy = getNullEmptyString(content.get(i).split(" "),2);
            }
        }
        if (!CCSD_energy.equals("")){
            form_data.put("CCSD_energy",CCSD_energy);
        }
        //读取log文件内容
        if (!keys_file_path.contains(log_file_path)){
            content = FileUtil.readFile(log_file_path);
            for (int i = 0;i<content.size();i++) {
                if (content.get(i).contains("*")) {
                    form_data.put("Program", content.get(i + 1).split(":")[0]);
                    form_data.put("Sub_system_program", getNullEmptyString(content.get(i + 1).split(":")[1].split(" "), 0));
                    break;
                }
            }
        }

        return form_data;
    }

    /**
     * 从磁盘中读取分析Dmol3所需文件
     * @param cif_file_path
     * @param dosOutmol_file_path
     * @param bandStrOutmol_file_path
     * @param outmol_file_path
     * @return
     * @throws Exception
     */
    public static HashMap<String,String> readAndProcess_dmol3File(String cif_file_path,
                                                                  String outmol_file_path,
                                                                  String dosOutmol_file_path,
                                                                  String bandStrOutmol_file_path) throws Exception{
        ArrayList<String> content = new ArrayList<>();
        HashMap<String,String> form_data = new HashMap<String,String>(){{
            put("Lattice_parameters_length","null");
            put("Lattice_parameters_angle","null");
            put("Space_group","null");
            put("Crystal_CrystalSystem","null");
            put("Crystal_Grid","null");
            put("priAtomic","null");
            put("Crystal_Multiplicity","null");
            put("Crystal_Charge","null");
            put("Program","Material studio");
            put("node","null");
            put("Thermal_occupancy_effect","null");
            put("Truncation_radius","null");
            put("Kpoints","null");
            put("Calculated_level","null");
            put("Basis","null");
            put("energy","null");
            put("atomic","null");
            put("x_coor","null");
            put("y_coor","null");
            put("z_coor","null");
            put("Fermi_energy_ha","null");
            put("Fermi_energy_ev","null");
            put("valence_band_edge_ha","null");
            put("valence_band_edge_ev","null");
            put("conduction_band_edge_ha","null");
            put("conduction_band_edge_ev","null");
            put("HOMO", "null");
            put("LUMO", "null");
            put("HOMO_LUMO","null");
        }};

        String temp;
//        读取cif文件内容
        if (!outmol_file_path.contains(cif_file_path)){
            content = FileUtil.readFile(cif_file_path);
            for (int i = 0; i < content.size();i++){
                if (content.get(i).contains("_cell_length_a")){
                    temp = getNullEmptyString(content.get(i).split(" "),1)+";"+getNullEmptyString(content.get(i+1).split(" "),1)+";"+getNullEmptyString(content.get(i+2).split(" "),1);
                    form_data.put("Lattice_parameters_length",temp);
                    i = i + 2;
                }
                if (content.get(i).contains("_cell_angle_alpha")){
                    temp = getNullEmptyString(content.get(i).split(" "),1)+";"+getNullEmptyString(content.get(i+1).split(" "),1)+";"+getNullEmptyString(content.get(i+2).split(" "),1);
                    form_data.put("Lattice_parameters_angle",temp);
                    i = i + 2;
                }
                if (content.get(i).contains("_symmetry_space_group_name_H-M")){
                    form_data.put("Space_group",getNullEmptyString(content.get(i).split(" "),1));
                }
            }
        }

//        读取outmol文件内容
        content = FileUtil.readFile(outmol_file_path);
        boolean decision = true;
        for (int i = 0;i<content.size();i++){
            if (content.get(i).contains("The point group of the crystal is:")){
                form_data.put("Crystal_CrystalSystem",getNullEmptyString(content.get(i+1).split(" "),0));
            }
            if (content.get(i).contains("$cell vectors")){
                temp = "";
                for(int j = 1; !content.get(i+j).contains("$coordinates");j++){
                    ArrayList<String> temp_vectors = getNullEmptyStringArray(content.get(i+j).split(" "));
                    temp += temp_vectors.get(0)+";"+temp_vectors.get(1)+";"+temp_vectors.get(2)+";";
                }
                form_data.put("Crystal_Grid",temp);
            }
            if (content.get(i).contains("$coordinates")){
                String priAtomic = "";
                for(int j = 1; !content.get(i+j).contains("$end");j++){
                    priAtomic = priAtomic + getNullEmptyString(content.get(i+j).split(" "),0) + ";";
                }
                form_data.put("priAtomic",priAtomic);
            }
            if (content.get(i).contains("This run uses")&&decision){
                String pattern = "(\\D*)(\\d+)(.*)";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(content.get(i));
                m.find();
                form_data.put("node",m.group(2));
                decision = false;
            }
            if (content.get(i).contains("Coordinates (Angstroms)")){
                String atomic = "";
                String x_coor = "";
                String y_coor = "";
                String z_coor = "";
                for(int j = 3; !content.get(i+j).contains("--------------");j++){
                    ArrayList<String> temp_coor = getNullEmptyStringArray(content.get(i+j).split(" "));
                    atomic = atomic + temp_coor.get(1) + ";";
                    x_coor = x_coor + temp_coor.get(2) + ";";
                    y_coor = y_coor + temp_coor.get(3) + ";";
                    z_coor = z_coor + temp_coor.get(4) + ";";
                }
                form_data.put("atomic",atomic);
                form_data.put("x_coor",x_coor);
                form_data.put("y_coor",y_coor);
                form_data.put("z_coor",z_coor);
            }
            if (content.get(i).contains("Electronic parameters")){
                for (int j=1;j<=16;j++){
                    if (content.get(i+j).contains("Spin_polarization")){
                        form_data.put("Crystal_Multiplicity",getNullEmptyString(content.get(i+j).split(" "),1));
                    }
                    if (content.get(i+j).contains("Charge")){
                        form_data.put("Crystal_Charge",getNullEmptyString(content.get(i+j).split(" "),1));
                    }
                    if (content.get(i+j).contains("Basis")){
                        if (content.get(i+j+1).contains("basis_version")){
                            form_data.put("Basis",getNullEmptyString(content.get(i+j).split(" "),1)+","+getNullEmptyString(content.get(i+j+1).split(" "),1));
                        }else {
                            form_data.put("Basis",getNullEmptyString(content.get(i+j).split(" "),1));
                        }
                    }
                    if (content.get(i+j).contains("Functional")){
                        form_data.put("Calculated_level",getNullEmptyString(content.get(i+j).split(" "),1));
                    }
                    if (content.get(i+j).contains("Occupation")){
                        ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i+j).split(" "));
                        tempArr.remove(0);
                        tempArr.remove(tempArr.size()-1);
                        form_data.put("Thermal_occupancy_effect", StringUtils.join(tempArr," "));
                    }
                    if (content.get(i+j).contains("Cutoff_Global")){
                        ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i+j).split(" "));
                        tempArr.remove(0);
                        tempArr.remove(tempArr.size()-1);
                        form_data.put("Truncation_radius", StringUtils.join(tempArr," "));
                    }
                }
            }
            if (content.get(i).contains("Kpoint definition file")){
                ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i+1).split(" "));
                tempArr.remove(0);
                tempArr.remove(0);
                tempArr.remove(tempArr.size()-1);
                form_data.put("Kpoints", StringUtils.join(tempArr," "));
            }
            if (content.get(i).contains("Fermi Energy")){
                ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i).split(":")[1].split(" "));
                form_data.put("Fermi_energy_ha", tempArr.get(0));
                form_data.put("Fermi_energy_ev", tempArr.get(2));
            }
            if (content.get(i).contains("valence band edge")){
                ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i).split(":")[1].split(" "));
                form_data.put("valence_band_edge_ha", tempArr.get(0));
                form_data.put("valence_band_edge_ev", tempArr.get(2));
            }
            if (content.get(i).contains("conduction band edge")){
                ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i).split(":")[1].split(" "));
                form_data.put("conduction_band_edge_ha", tempArr.get(0));
                form_data.put("conduction_band_edge_ev", tempArr.get(2));
            }
            if (content.get(i).contains("Energy of Highest Occupied Molecular Orbital")){
                form_data.put("HOMO", getNullEmptyString(content.get(i).split(":")[1].split(" "),0).replace("Ha",""));
                form_data.put("LUMO", getNullEmptyString(content.get(i+1).split(":")[1].split(" "),0).replace("Ha",""));
                Double HOMO_LUMO= Double.parseDouble(form_data.get("HOMO"))-Double.parseDouble(form_data.get("LUMO"));
                HOMO_LUMO = (double)Math.round(HOMO_LUMO*100000)/100000;
                form_data.replace("HOMO_LUMO",HOMO_LUMO.toString());
            }
            if (content.get(i).contains("Cycle    Total Energy")){
                if (form_data.get("energy").contains("null")){
                    form_data.put("energy", getNullEmptyString(content.get(i+2).split(" "),2));
                }else {
                    form_data.put("energy", getNullEmptyString(content.get(i+1).split(" "),2));
                }

            }
        }

        return form_data;
    }

    /**
     * 从磁盘中读取分析Castep所需文件
     * @param cif_file_path
     * @param castep_file_path
     * @param dosCastep_file_path
     * @param bandStrCastep_file_path
     * @return
     * @throws Exception
     */
    public static HashMap<String,String> readAndProcess_CastepFile(String cif_file_path,
                                                                    String castep_file_path,
                                                                    String dosCastep_file_path,
                                                                    String bandStrCastep_file_path) throws Exception{
        ArrayList<String> content = new ArrayList<>();
        HashMap<String,String> form_data = new HashMap<String,String>(){{
            put("Lattice_parameters_length","null");
            put("Lattice_parameters_angle","null");
            put("Crystal_Grid","null");
            put("Crystal_electronsNum","null");
            put("Crystal_upSpinsNum","null");
            put("Crystal_downSpinsNum","null");
            put("Crystal_bandsNum","null");
            put("Program","null");
            put("node","null");
            put("Kpoints","null");
            put("Calculated_level","null");
            put("Optimization_method","null");
            put("energy_ev","null");
            put("atomic","null");
            put("x_coor","null");
            put("y_coor","null");
            put("z_coor","null");
            put("Fermi_energy_ha","null");
            put("Bond_length","null");
            put("volume","null");
            put("Final_Free_Energy","null");
        }};

        String temp;
//        读取castep文件内容
        content = FileUtil.readFile(castep_file_path);
        form_data.put("Program","Material studio");
        for (int i = 0;i<content.size();i++){
            if (content.get(i).contains("Lattice parameters(A)")){
                form_data.put("Lattice_parameters_length",getNullEmptyString(content.get(i+1).split(" "),2)+";"+getNullEmptyString(content.get(i+2).split(" "),2)+";"+getNullEmptyString(content.get(i+3).split(" "),2));
                form_data.put("Lattice_parameters_angle",getNullEmptyString(content.get(i+1).split(" "),5)+";"+getNullEmptyString(content.get(i+2).split(" "),5)+";"+getNullEmptyString(content.get(i+3).split(" "),5));
            }
            if (content.get(i).contains("Real Lattice(A)")){
                temp = "";
                for(int j = 1;j<4;j++){
                    ArrayList<String> temp_vectors = getNullEmptyStringArray(content.get(i+j).split(" "));
                    temp += temp_vectors.get(0)+";"+temp_vectors.get(1)+";"+temp_vectors.get(2)+";";
                }
                form_data.put("Crystal_Grid",temp);
            }
            if (content.get(i).contains("Electronic Parameters")){
                for (int j = 2;j<9;j++){
                    if (content.get(i+j).contains("number of  electrons")){
                        form_data.put("Crystal_electronsNum",getNullEmptyString(content.get(i+j).split(":")[1].split(" "),0));
                    }
                    if (content.get(i+j).contains("number of  up  spins")){
                        form_data.put("Crystal_upSpinsNum",getNullEmptyString(content.get(i+j).split(":")[1].split(" "),0));
                    }
                    if (content.get(i+j).contains("number of down spins")){
                        form_data.put("Crystal_downSpinsNum",getNullEmptyString(content.get(i+j).split(":")[1].split(" "),0));
                    }
                    if (content.get(i+j).contains("number of bands")){
                        form_data.put("Crystal_bandsNum",getNullEmptyString(content.get(i+j).split(":")[1].split(" "),0));
                    }
                }
            }
            if (content.get(i).contains("Calculation parallelised over")){
                String pattern = "(\\D*)(\\d+)(.*)";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(content.get(i));
                m.find();
                form_data.put("node",m.group(2));
            }
            if (content.get(i).contains("k-Points")){
                ArrayList<String> tempArr = getNullEmptyStringArray(content.get(i+2).split(" "));
                temp = "";
                for (int j=0;j<tempArr.size();j++){
                    if (isNumeric(tempArr.get(j))){
                        temp += tempArr.get(j)+" ";
                    }
                }
                form_data.put("Kpoints",temp);
            }
            if (content.get(i).contains("using functional")){
                form_data.put("Calculated_level",content.get(i).split(":")[1]);
            }
            if (content.get(i).contains("optimization method")){
                form_data.put("Optimization_method",getNullEmptyString(content.get(i).split(":"),1));
            }
            if (content.get(i).contains("Final energy")){
                form_data.put("energy_ev",getNullEmptyString(content.get(i).split("=")[1].split(" "),0));
            }
            if (content.get(i).contains("Fractional coordinates of atoms")){
                String atomic = "";
                String x_coor = "";
                String y_coor = "";
                String z_coor = "";
                for(int j = 1; !content.get(i+2+j).contains("xxxxxxxxxx");j++){
                    ArrayList<String> temp_coor = getNullEmptyStringArray(content.get(i+2+j).split(" "));
                    atomic = atomic + temp_coor.get(1) + ";";
                    x_coor = x_coor + temp_coor.get(3) + ";";
                    y_coor = y_coor + temp_coor.get(4) + ";";
                    z_coor = z_coor + temp_coor.get(5) + ";";
                }
                form_data.put("atomic",atomic);
                form_data.put("x_coor",x_coor);
                form_data.put("y_coor",y_coor);
                form_data.put("z_coor",z_coor);
            }
            if (content.get(i).contains("Fermi energy convergence tolerance")){
                form_data.put("Fermi_energy_ha",getNullEmptyString(content.get(i).split(":")[1].split(" "),0));
            }
            if (content.get(i).contains("Bond")){
                temp = "";
                for(int j = 1; !content.get(i+1+j).contains("==========");j++){
                    ArrayList<String> temp_bond = getNullEmptyStringArray(content.get(i+1+j).split("  "));
                    temp += temp_bond.get(0).replace(" ","") + ": " + temp_bond.get(2) + ";";
                }
                form_data.put("Bond_length",temp);
            }
            if (content.get(i).contains("Current cell volume")){
                form_data.put("volume",getNullEmptyString(content.get(i).split("=")[1].split(" "),0));
            }
            if (content.get(i).contains("Final free energy")){
                form_data.put("Final_Free_Energy",getNullEmptyString(content.get(i).split("=")[1].split(" "),0));
            }
        }

        return form_data;
    }

    /**
     * 从磁盘中读取分析Vasp所需文件
     * @param incar_file_path
     * @param poscar_file_path
     * @param potcar_file_path
     * @param cif_file_path
     * @param kpoints_file_path
     * @param contcar_file_path
     * @param outcar_file_path
     * @return
     * @throws Exception
     */
    public static HashMap<String,String> readAndProcess_VaspFile(String incar_file_path,
                                                                 String poscar_file_path,
                                                                 String potcar_file_path,
                                                                 String cif_file_path,
                                                                 String kpoints_file_path,
                                                                 String contcar_file_path,
                                                                 String outcar_file_path) throws Exception{
        ArrayList<String> content = new ArrayList<>();
        HashMap<String,String> form_data = new HashMap<String,String>(){{
            put("Lattice_parameters_length","null");
            put("Lattice_parameters_angle","null");
            put("Space_group","null");
            put("priAtomic","null");
            put("priAtomic_num","null");
            put("Crystal_Grid","null");
            put("Program","null");
            put("Kpoints","null");
            put("Calculated_level","null");
            put("energy_ev","null");
            put("atomic","null");
            put("x_coor","null");
            put("y_coor","null");
            put("z_coor","null");
            put("Fermi_energy_ev","null");
            put("volume","null");
        }};

        String temp;
        //按行读取poscar_cif文件内容
        if (!outcar_file_path.contains(cif_file_path)){
            content = FileUtil.readFile(cif_file_path);
            form_data.put("Program","Material studio");
            for (int i = 0;i<content.size();i++){
                if (content.get(i).contains("_cell_length_a")){
                    form_data.put("Lattice_parameters_length",getNullEmptyString(content.get(i).split(" "),1)+";"+getNullEmptyString(content.get(i+1).split(" "),1)+";"+getNullEmptyString(content.get(i+2).split(" "),1));
                    form_data.put("Lattice_parameters_angle",getNullEmptyString(content.get(i+3).split(" "),1)+";"+getNullEmptyString(content.get(i+4).split(" "),1)+";"+getNullEmptyString(content.get(i+5).split(" "),1));
                    form_data.put("Space_group",getNullEmptyString(content.get(i+6).split("'"),1));
                }
            }
        }

        //按行读取poscar文件内容
        if (!outcar_file_path.contains(poscar_file_path) && form_data.get("atomic").equals("null")){
            content = FileUtil.readFile(poscar_file_path);
            form_data.put("priAtomic", StringUtils.join(getNullEmptyStringArray(content.get(5).split(" ")),';'));
            form_data.put("priAtomic_num",StringUtils.join(getNullEmptyStringArray(content.get(6).split(" ")),';'));
            String[] priAtomic = form_data.get("priAtomic").split(";");
            String[] priAtomic_num = form_data.get("priAtomic_num").split(";");
            String atomic = "";
            for (int i = 0;i< priAtomic.length;i++){
                String single_atomic = priAtomic[i];
                for (int j = 0; j< Integer.valueOf(priAtomic_num[i]) ;j++){
                    atomic += single_atomic + ';';
                }
            }
            form_data.put("atomic",atomic);
        }

        //按行读取Kpoint文件内容
        if (!outcar_file_path.contains(kpoints_file_path)){
            content = FileUtil.readFile(kpoints_file_path);
            form_data.put("Kpoints", StringUtils.join(getNullEmptyStringArray(content.get(3).split(" ")),' ')+' '+StringUtils.join(getNullEmptyStringArray(content.get(4).split(" ")),' '));
        }

        //按行读取contcar文件内容
        if(!outcar_file_path.contains(contcar_file_path)){
            content = FileUtil.readFile(contcar_file_path);
            form_data.put("priAtomic", StringUtils.join(getNullEmptyStringArray(content.get(5).split(" ")),';'));
            form_data.put("priAtomic_num",StringUtils.join(getNullEmptyStringArray(content.get(6).split(" ")),';'));
            String[] priAtomic = form_data.get("priAtomic").split(";");
            String[] priAtomic_num = form_data.get("priAtomic_num").split(";");
            String atomic = "";
            for (int i = 0;i< priAtomic.length;i++){
                String single_atomic = priAtomic[i];
                for (int j = 0; j< Integer.valueOf(priAtomic_num[i]) ;j++){
                    atomic += single_atomic + ';';
                }
            }
            form_data.put("atomic",atomic);
        }

        //按行读取outcar文件内容
        content = FileUtil.readFile(outcar_file_path);
        for (int i = 0;i<content.size();i++){
            if (content.get(i).contains("INCAR:")){
                String[] Calculated_level = getNullEmptyString(content.get(i+1).split(":")[1].split(" "),0).split("_")[1].split("_");
                if (Calculated_level.length >= 2){
                    form_data.put("Calculated_level",Calculated_level[1]);
                }else {
                    form_data.put("Calculated_level",Calculated_level[0]);
                }
            }
            if (content.get(i).contains("volume of cell")){
                form_data.put("volume",getNullEmptyString(content.get(i).split(":")[1].split(" "),0));
            }
            if (content.get(i).contains("direct lattice vectors")){
                String lattice_vectors = "";
                for (int j = 1 ; !content.get(i+j+1).contains("length of vectors"); j++){
                    lattice_vectors += StringUtils.join(getNullEmptyStringArray(content.get(i+j).split(" ")).subList(0,3),';') + ';';
                }
                form_data.put("Crystal_Grid",lattice_vectors);
            }
            if (content.get(i).contains("energy without entropy")){
                form_data.put("energy_ev",getNullEmptyString(content.get(i).split("=")[1].split(" "),0));
            }
            if (content.get(i).contains("TOTAL-FORCE (eV/Angst)")){
                String x_coor = "";
                String y_coor = "";
                String z_coor = "";
                for(int j = 2; !content.get(i+j).contains("-------------------");j++){
                    ArrayList<String> temp_coor = getNullEmptyStringArray(content.get(i+2).split(" "));
                    x_coor = x_coor + temp_coor.get(0) + ";";
                    y_coor = y_coor + temp_coor.get(1) + ";";
                    z_coor = z_coor + temp_coor.get(2) + ";";
                }
                form_data.put("x_coor",x_coor);
                form_data.put("y_coor",y_coor);
                form_data.put("z_coor",z_coor);
            }
            if (content.get(i).contains("Fermi energy")){
                form_data.put("Fermi_energy_ev",getNullEmptyString(content.get(i).split(";")[0].split(":"),2));
            }
        }

        return form_data;
    }

    /**
     * 根据关键词搜索数据库qm数据
     * @param base
     * @param keyword
     * @return
     */
    public static ArrayList<ArrayList<String>> searchQM_data_by_keyword(String base,String keyword){
        ArrayList<String> join_table_names = new ArrayList<String>(){{
            add("QM_Electronic_Structure_Quantum_Mechanics_Calculation");
            add("QM_Ground_state");
        }};
        DBconnection saveInDB = new DBconnection();

        String table_name = base_index_compute.get(base).split("-")[0];
        String col_name = base_index_compute.get(base).split("-")[1];         //查询字段

        saveInDB.setSheet_name(table_name);    //查询表
        //假设用户只选择同一计算对象数据

        join_table_names.add(0,"QM_CalculationObject_SolventSolute");
        join_table_names.add(0,"QM_CalculationObject_Crystal");
        join_table_names.add(0,"QM_CalculationObject_Slab");

//        join_table_names.add(0,"QM_CalculationObject_SolventSolute");
//        join_table_names.add(0,"QM_CalculationObject_Crystal");
//        join_table_names.add(0,"QM_CalculationObject_Slab");
        return saveInDB.getFormDataJoinTable(col_name, "id",keyword, join_table_names);

    }

    //查询id
//    private static ArrayList<String> getID_by_keyword(DBconnection saveInDB,String base,String keyword){
//
//        String table_name = base_index_compute.get(base).split("-")[0];
//        String col_name = base_index_compute.get(base).split("-")[1];
//
//        saveInDB.setSheet_name(table_name);
//        return saveInDB.getIdByKeyword(keyword, table_name, col_name);
//    }

    /**
     * 获取QM表标题
     * @return
     */
    public static ArrayList<String> getTiltlName(String selected_id){

        ArrayList<String> table_names = new ArrayList<String>(){{
            add("QM_USER_AND_PBC");
            add("QM_Electronic_Structure_Quantum_Mechanics_Calculation");
            add("QM_Ground_state");
        }};

        DBconnection saveInDB = new DBconnection();

        saveInDB.setSheet_name("QM_USER_AND_PBC");
//        switch(saveInDB.getDataFromRow(selected_id,"caculation_object")){
//            case "QM_CalculationObject_Slab": table_names.add(1,"QM_CalculationObject_Slab"); break;
//            case "QM_CalculationObject_Crystal": table_names.add(1,"QM_CalculationObject_Crystal"); break;
//            case "QM_CalculationObject_SolventSolute": table_names.add(1,"QM_CalculationObject_SolventSolute"); break;
//        }

        table_names.add(1,"QM_CalculationObject_SolventSolute");
        table_names.add(1,"QM_CalculationObject_Crystal");
        table_names.add(1,"QM_CalculationObject_Slab");

        ArrayList<String> title = new ArrayList<>();
        for (int i = 0;i < table_names.size();i++){

            saveInDB.setSheet_name(table_names.get(i));
            ArrayList<String> temp_title = saveInDB.getTitleFromDB();
            if(i != 0){
                temp_title.remove(0);
            }
            title.addAll(temp_title);
        }

        return title;
    }
}
